﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Media;

namespace theeg.GraphWpf.Models
{
    public class SubGraph : Node, IGraph
    {
        private readonly IList<INode> _nodes = new List<INode>();

        public IList<INode> Nodes
        {
            get { return _nodes; }
        }

        private readonly IList<Transition> _transitions = new List<Transition>();

        public IList<Transition> Transitions
        {
            get { return _transitions; }
        }

        public IArrangement Arrangement { get; set; }

        private bool _isExpanded;

        public bool IsExpanded
        {
            get { return _isExpanded; }
            set
            {
                SetNotifyingField(ref _isExpanded, value, "IsExpanded");
                CoerceWidth();
                CoerceHeight();
            }
        }

        private double _contentHeight;

        public double ContentHeight
        {
            get { return _contentHeight; }
            set
            {
                SetNotifyingField(ref _contentHeight, value, "ContentHeight");
                CoerceHeight();
            }
        }

        private double _contentWidth;

        public double ContentWidth
        {
            get { return _contentWidth; }
            set
            {
                SetNotifyingField(ref _contentWidth, value, "ContentWidth");
                CoerceWidth();
            }
        }

        private double _collapsedHeight;

        public double CollapsedHeight
        {
            get { return _collapsedHeight; }
            set
            {
                SetNotifyingField(ref _collapsedHeight, value, "CollapsedHeight");
                CoerceHeight();
            }
        }

        private double _collapsedWidth;

        public double CollapsedWidth
        {
            get { return _collapsedWidth; }
            set
            {
                SetNotifyingField(ref _collapsedWidth, value, "CollapsedWidth");
                CoerceWidth();
            }
        }
        private Transform _topLeftContent;

        public Transform TopLeftContent
        {
            get { return _topLeftContent; }
            set { SetNotifyingField(ref _topLeftContent, value, "TopLeftContent"); }
        }

        private Brush _fill;
        public Brush Fill
        {
            get { return _fill; }
            set { SetNotifyingField(ref _fill, value, "Fill"); }
        }

        private void CoerceHeight()
        {
            if (IsExpanded)
            {
                Height = CollapsedHeight + ContentHeight + 20;
            }
            else
            {
                Height = CollapsedHeight;
            }
        }

        private void CoerceWidth()
        {
            if (IsExpanded)
            {
                Width = Math.Max(CollapsedWidth, ContentWidth + 20);
            }
            else
            {
                Width = CollapsedWidth;
            }
        }

        public void Arrange()
        {
            if (Nodes.Count == 0) return;
            foreach (Node n in _nodes.OfType<Node>())
            {
                n.SuppressPropertyChanged = true;
            }
            foreach (var transition in _transitions)
            {
                transition.ClearControlPoints();
            }
            foreach (IGraph subgraph in _nodes.OfType<IGraph>())
            {
                if (subgraph.IsExpanded)
                {
                    subgraph.Arrange();
                }
            }
            if (Arrangement != null)
            {
                Arrangement.Arrange();
            }

            double minx = double.MaxValue;
            double miny = double.MaxValue;
            double maxx = double.MinValue;
            double maxy = double.MinValue;

            foreach (Node n in _nodes.OfType<Node>())
            {
                minx = Math.Min(minx, n.Left);
                miny = Math.Min(miny, n.Top);
                maxx = Math.Max(maxx, n.Left + n.Width);
                maxy = Math.Max(maxy, n.Top + n.Height);
                n.SuppressPropertyChanged = false;
                n.RaisePropertyChanged("CenterX");
                n.RaisePropertyChanged("CenterY");
            }
            double width = Math.Max(maxx - minx, 0);
            double height = Math.Max(maxy - miny, 0);
            ContentWidth = width;
            ContentHeight = height;
            if (minx == double.MaxValue)
            {
                TopLeftContent = Transform.Identity;
            }
            else
            {
                TopLeftContent = new TranslateTransform(-minx, -miny);
            }
            CoerceWidth();
            CoerceHeight();
        }
    }
}
